package com.jp.knowledge.comm;

import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Looper;
import android.os.Process;

import com.jiayen.cache.FileCacheManager;
import com.jiayen.util.ToasUtil;
import com.jp.knowledge.util.L;
import com.umeng.analytics.MobclickAgent;

import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;

/**
 * Created by jiayen on 16/12/27.
 *
 * 全局异常捕获
 */
public class JpCrashHandler implements Thread.UncaughtExceptionHandler {
    private static JpCrashHandler  crashHandler;

    private JpApplication application;
    private Thread.UncaughtExceptionHandler  defaulCaugh;
    private Context mContext;

    private Map<String,String> mInfos;

    private FileCacheManager fileCacheManager;

    public String exceptionPath;
    /**
     * 初始化
     * @param context
     */
    public void init(Context context){
        this.mContext=context;
        application = (JpApplication) context;
        Thread.setDefaultUncaughtExceptionHandler(this);
        defaulCaugh = Thread.getDefaultUncaughtExceptionHandler();
        mInfos =new HashMap<>();
        fileCacheManager = new FileCacheManager();
        exceptionPath=mContext.getCacheDir()+"/exception_"  + ".dat";//banner缓存路径
    }

    private JpCrashHandler(){}

    public static JpCrashHandler  getInstance(){
        if(crashHandler==null)crashHandler=new JpCrashHandler();
        return  crashHandler;
    }
    @Override
    public void uncaughtException(Thread t, Throwable e) {

        if(isHandException(e)){
            handlerException(e);
        }else {
            defaulCaugh.uncaughtException(t,e);
        }

    }

    /**
     * 处理异常
     * @param exception
     */
    private void handlerException(final Throwable exception) {

        try {
            L.e(exception.getMessage());
            Thread.sleep(2*1000);
            //退出程序
            application.finish();
            Process.killProcess(Process.myPid());
            System.exit(0);
            exception.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }


    /**
     * 上传异常到服务器
     * @param exception
     */
    private void sendExceptionToServer(Throwable exception) {
        //保存到本机缓存 方便查看
        fileCacheManager.wirteObject(exception.getMessage(),exceptionPath);

//        collectDeviceInfo(context);
        MobclickAgent.reportError(mContext,exception);//传错误日志到友盟服务器
    }


    /**
     * 过滤要捕获的异常
     * @param exception
     * @return
     */
    private boolean isHandException(final  Throwable exception){
        if(exception==null){
            return false;
        }

        new  Thread(new Runnable() {
            @Override
            public void run() {
                Looper.prepare();
                ToasUtil.toast(mContext,"荐识调皮了,将在2秒钟后罢工!");
                Looper.loop();

                //上传异常至服务器
                sendExceptionToServer(exception);

            }
        }).start();

        return true;
    }

    /**
     * 5.1 收集设备信息
     *
     * @param ctx
     */
    protected void collectDeviceInfo(Context ctx) {
        L.i("DRCrashHandler is collecting DeviceInfo! ");

        try {
            PackageManager pm = ctx.getPackageManager();
            PackageInfo pi = pm.getPackageInfo(ctx.getPackageName(), PackageManager.GET_ACTIVITIES);
            if (pi != null) {
                String versionName = pi.versionName == null ? "null" : pi.versionName;
                String versionCode = pi.versionCode + "";
                mInfos.put("versionName", versionName);
                mInfos.put("versionCode", versionCode);
            }
        } catch (PackageManager.NameNotFoundException e) {
            L.e("An error occured when collect package info, Error: " + e);
        }
        Field[] fields = Build.class.getDeclaredFields();
        for (Field field : fields) {
            try {
                field.setAccessible(true);
                mInfos.put(field.getName(), field.get(null).toString());
            } catch (Exception e) {
                L.e("An error occured when collect crash info, Error: " + e);
            }
        }
    }


}
